package netty.server;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;

@Slf4j
public class HttpHelloServerHandler extends SimpleChannelInboundHandler<HttpObject> {

    static final byte[] CONTENT = ("君不见黄河之水天上来，奔流到海不复回。\n" +
            "君不见高堂明镜悲白发，朝如青丝暮成雪。\n" +
            "人生得意须尽欢，莫使金樽空对月。\n" +
            "天生我材必有用，千金散尽还复来。\n" +
            "烹羊宰牛且为乐，会须一饮三百杯。\n" +
            "岑夫子，丹丘生，将进酒，杯莫停。\n" +
            "与君歌一曲，请君为我倾耳听。(倾耳听 一作：侧耳听)\n" +
            "钟鼓馔玉不足贵，但愿长醉不愿醒。(不足贵 一作：何足贵；不愿醒 一作：不复醒)\n" +
            "古来圣贤皆寂寞，惟有饮者留其名。(古来 一作：自古；惟 通：唯)\n" +
            "陈王昔时宴平乐，斗酒十千恣欢谑。\n" +
            "主人何为言少钱，径须沽取对君酌。\n" +
            "五花马、千金裘，呼儿将出换美酒，与尔同销万古愁。").getBytes(StandardCharsets.UTF_8);

    public HttpHelloServerHandler() {
        log.info(">>> init {}", this.toString());
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        log.info("receive data: {}, {}", msg, ctx.channel().remoteAddress());

        if (msg instanceof HttpRequest) {
            HttpRequest req = (HttpRequest) msg;

            boolean keepAlive = HttpUtil.isKeepAlive(req);
            FullHttpResponse response = new DefaultFullHttpResponse(req.protocolVersion(), HttpResponseStatus.OK, Unpooled.wrappedBuffer(CONTENT));
            response.headers()
                    .set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8")
                    //.set(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.TEXT_PLAIN)
                    .setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());

            if (keepAlive) {
                if (!req.protocolVersion().isKeepAliveDefault()) {
                    response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
                }
            } else {
                // Tell the client we're going to close the connection.
                response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);
            }

            ChannelFuture f = ctx.write(response);

            if (!keepAlive) {
                f.addListener(ChannelFutureListener.CLOSE);
            }
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // Close the connection when an exception is raised.
        cause.printStackTrace();
        ctx.close();
    }
}